using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using FiltronASP.Logger;
using FiltronASP.Helpers.Constants;

namespace FiltronASP.Models.DAO.Filtron
{
    public class FiltronFilterDAO : Abstracts.AbstractGenericDAO<FiltronFilter, System.Nullable<int>>,
        Interfaces.Filtron.IFiltronFilterDAO
    {
        /// <summary>
        /// Metoda zwracajaca nazwe parametru bedacego kluczem glownym tabeli.
        /// </summary>
        /// <returns>nazwa klucza glownego</returns>
        protected override string GetKeyProperty()
        {
            return "filter_id";
        }

        /// <summary>
        /// Pobieranie obiektow na podstawie silnika.
        /// </summary>
        /// <param name="engineId">silnik</param>
        /// <returns>rekordy o zadanym silniku lub null, gdy nie ma</returns>
        public IQueryable<FiltronFilter> FindByEngine(int engineId)
        {
            if (engineId.Equals(0))
            {
                return null;
            }   //if
            try
            {
                IQueryable<FiltronFilter> filters = this._cmsEntitiesDataContext.FiltronFilters.Where(
                    filt => this._cmsEntitiesDataContext.FiltronFilterEngines.Where(fien =>
                        fien.engine_id.Equals(engineId)).Select(fe => fe.filter_id).Contains(filt.filter_id)
                        );
                if (!(filters.Any()))
                {
                    return null;
                }   //if
                return filters;
            }   //try
            catch (Exception ex)
            {
                MyLogger.Log(ex);
            }   //catch
            return null;
        }

        /// <summary>
        /// Pobieranie obiektow na podstawie silnika i modelu.
        /// </summary>
        /// <param name="engineId">silnik</param>
        /// <param name="modelId">model</param>
        /// <returns>rekordy o zadanym silniku i modelu lub null, gdy nie ma</returns>
        public IQueryable<FiltronFilter> FindByEngineAndModel(int engineId, int modelId)
        {
            if (engineId.Equals(0))
            {
                return null;
            }   //if
            if (modelId.Equals(0))
            {
                return null;
            }
            try
            {
                IQueryable<FiltronFilter> filters = this._cmsEntitiesDataContext.FiltronFilters.Where(
                    filt => this._cmsEntitiesDataContext.FiltronFilterEngines.Where(fien =>
                        fien.engine_id.Equals(engineId) &&
                        fien.model_id.HasValue &&
                        fien.model_id.Equals(modelId)).Select(fe => fe.filter_id).Contains(filt.filter_id)
                        );
                if (!(filters.Any()))
                {
                    return null;
                }   //if
                return filters;
            }   //try
            catch (Exception ex)
            {
                MyLogger.Log(ex);
            }   //catch
            return null;
        }

        /// <summary>
        /// Pobieranie obiektow na podstawie numeru filtra.
        /// </summary>
        /// <param name="filterNumber">numer</param>
        /// <returns>rekordy o zadanym numerze filtra</returns>
        public IQueryable<FiltronFilter> FindByFilterNumber(string filterNumber)
        {
            if (filterNumber == String.Empty)
            {
                return null;
            }   //if
            try
            {
                IQueryable<FiltronFilter> filters = this._cmsEntitiesDataContext.FiltronFilters.Where(
                    filt => filt.filter_number_trim.ToLower().Contains(filterNumber.ToLower())
                        ).OrderBy(filt => filt.filter_number_trim);
                if (!(filters.Any()))
                {
                    return null;
                }   //if
                return filters;
            }   //try
            catch (Exception ex)
            {
                MyLogger.Log(ex);
            }   //catch
            return null;
        }

        public IQueryable<FiltronFilter> FindByWixFilterNumber(string wixFilterNumber)
        {
            if (wixFilterNumber == String.Empty)
            {
                return null;
            }   //if
            try
            {
                IQueryable<FiltronFilter> filters = this._cmsEntitiesDataContext.FiltronFilters.Where(
                    filt => (filt.filter_wix_number.ToLower().Equals(wixFilterNumber.ToLower())) || (filt.filter_wix_number_hd.ToLower().Equals(wixFilterNumber.ToLower()))
                        ).OrderBy(filt => filt.filter_number_trim);
                if (!(filters.Any()))
                {
                    return null;
                }   //if
                return filters;
            }   //try
            catch (Exception ex)
            {
                MyLogger.Log(ex);
            }   //catch
            return null;
        }

        public IQueryable<FiltronFilter> FindByWixFilterNumberContains(string wixFilterNumber)
        {
            if (wixFilterNumber == String.Empty)
            {
                return null;
            }   //if
            try
            {
                IQueryable<FiltronFilter> filters = this._cmsEntitiesDataContext.FiltronFilters.Where(
                    filt => (filt.filter_wix_number.ToLower().Contains(wixFilterNumber.ToLower())) || (filt.filter_wix_number_hd.ToLower().Contains(wixFilterNumber.ToLower()))
                        ).OrderBy(filt => filt.filter_number_trim);
                if (!(filters.Any()))
                {
                    return null;
                }   //if
                return filters;
            }   //try
            catch (Exception ex)
            {
                MyLogger.Log(ex);
            }   //catch
            return null;
        }

        public IQueryable<FiltronFilter> FindByWixFilterNumberContains(string wixFilterNumber, Constants.TSearchInclusionMode searchMode)
        {
            if (wixFilterNumber == String.Empty)
            {
                return null;
            }   //if
            try
            {
                IQueryable<FiltronFilter> filters = null;
                switch (searchMode)
                {
                    case Constants.TSearchInclusionMode.simBoth:
                        filters = this._cmsEntitiesDataContext.FiltronFilters.Where(
                            filt => (filt.filter_wix_number.ToLower().Contains(wixFilterNumber.ToLower())) || (filt.filter_wix_number_hd.ToLower().Contains(wixFilterNumber.ToLower()))
                                ).OrderBy(filt => filt.filter_number_trim);
                        break;
                    case Constants.TSearchInclusionMode.simExact:
                        filters = this._cmsEntitiesDataContext.FiltronFilters.Where(
                            filt => (filt.filter_wix_number.ToLower().Equals(wixFilterNumber.ToLower())) || (filt.filter_wix_number_hd.ToLower().Equals(wixFilterNumber.ToLower()))
                                ).OrderBy(filt => filt.filter_number_trim);
                        break;
                    case Constants.TSearchInclusionMode.simLeft:
                        filters = this._cmsEntitiesDataContext.FiltronFilters.Where(
                            filt => (filt.filter_wix_number.ToLower().StartsWith(wixFilterNumber.ToLower())) || (filt.filter_wix_number_hd.ToLower().StartsWith(wixFilterNumber.ToLower()))
                                ).OrderBy(filt => filt.filter_number_trim);
                        break;
                    case Constants.TSearchInclusionMode.simRight:
                        filters = this._cmsEntitiesDataContext.FiltronFilters.Where(
                            filt => (filt.filter_wix_number.ToLower().EndsWith(wixFilterNumber.ToLower())) || (filt.filter_wix_number_hd.ToLower().EndsWith(wixFilterNumber.ToLower()))
                                ).OrderBy(filt => filt.filter_number_trim);
                        break;
                }   //switch
                if (filters == null)
                {
                    return null;
                }   //if
                if (!(filters.Any()))
                {
                    return null;
                }   //if
                return filters;
            }   //try
            catch (Exception ex)
            {
                MyLogger.Log(ex);
            }   //catch
            return null;
        }

        public IQueryable<FiltronFilter> FindByWixFilterNumberContains(string wixFilterNumber, Constants.TSearchInclusionMode searchMode, int limit)
        {
            if (wixFilterNumber == String.Empty)
            {
                return null;
            }   //if
            try
            {
                if (limit <= 0)
                {
                    throw new Exception("Non-positive limit value");
                }   //if
                IQueryable<FiltronFilter> filters = null;
                switch (searchMode)
                {
                    case Constants.TSearchInclusionMode.simBoth:
                        filters = this._cmsEntitiesDataContext.FiltronFilters.Where(
                            filt => (filt.filter_wix_number.ToLower().Contains(wixFilterNumber.ToLower())) || (filt.filter_wix_number_hd.ToLower().Contains(wixFilterNumber.ToLower()))
                                ).OrderBy(filt => filt.filter_number_trim).Take(limit);
                        break;
                    case Constants.TSearchInclusionMode.simExact:
                        filters = this._cmsEntitiesDataContext.FiltronFilters.Where(
                            filt => (filt.filter_wix_number.ToLower().Equals(wixFilterNumber.ToLower())) || (filt.filter_wix_number_hd.ToLower().Equals(wixFilterNumber.ToLower()))
                                ).OrderBy(filt => filt.filter_number_trim).Take(limit); ;
                        break;
                    case Constants.TSearchInclusionMode.simLeft:
                        filters = this._cmsEntitiesDataContext.FiltronFilters.Where(
                            filt => (filt.filter_wix_number.ToLower().StartsWith(wixFilterNumber.ToLower())) || (filt.filter_wix_number_hd.ToLower().StartsWith(wixFilterNumber.ToLower()))
                                ).OrderBy(filt => filt.filter_number_trim).Take(limit);
                        break;
                    case Constants.TSearchInclusionMode.simRight:
                        filters = this._cmsEntitiesDataContext.FiltronFilters.Where(
                            filt => (filt.filter_wix_number.ToLower().EndsWith(wixFilterNumber.ToLower())) || (filt.filter_wix_number_hd.ToLower().EndsWith(wixFilterNumber.ToLower()))
                                ).OrderBy(filt => filt.filter_number_trim).Take(limit);
                        break;
                }   //switch
                if (filters == null)
                {
                    return null;
                }   //if
                if (!(filters.Any()))
                {
                    return null;
                }   //if
                return filters;
            }   //try
            catch (Exception ex)
            {
                MyLogger.Log(ex);
            }   //catch
            return null;
        }

        /// <summary>
        /// Pobieranie obiektow na podstawie typu.
        /// </summary>
        /// <param name="typeId">typ filtru</param>
        /// <returns>rekordy o zadanym typie lub null, gdy nie ma</returns>
        public IQueryable<FiltronFilter> FindByType(int typeId)
        {
            if (typeId.Equals(0))
            {
                return null;
            }   //if
            try
            {
                IQueryable<FiltronFilter> filters = this._cmsEntitiesDataContext.FiltronFilters.Where(
                    filt => filt.filter_type_id.Equals(typeId)
                        );
                if (!(filters.Any()))
                {
                    return null;
                }   //if
                return filters;
            }   //try
            catch (Exception ex)
            {
                MyLogger.Log(ex);
            }   //catch
            return null;
        }

        /// <summary>
        /// Pobieranie obiektow na podstawie wymiarow.
        /// </summary>
        /// <param name="height">wysokosc</param>
        /// <param name="width">szerokosc</param>
        /// <param name="length">dlugosc</param>
        /// <param name="outsideDiaTop">zewnetrzna gorna srednica</param>
        /// <param name="outsideDiaBottom">zewnetrzna dolna srednica</param>
        /// <param name="insideDiaTop">wewnetrzna gorna srednica</param>
        /// <param name="insideDiaBottom">wewnetrzna dolna srednica</param>
        /// <returns>rekordy o zadanych wymiarach lub null, gdy nie ma</returns>
        public IQueryable<FiltronFilter> FindByDimensions(
            decimal dimA, int dimAdiff,
            decimal dimB, int dimBdiff,
            decimal dimC, int dimCdiff,
            decimal dimD, int dimDdiff,
            decimal dimE, int dimEdiff,
            decimal dimF, int dimFdiff,
            decimal dimG, int dimGdiff,
            decimal dimH, int dimHdiff,
            int filterShape)
        {
            try
            {
                IQueryable<FiltronFilter> filters = this._cmsEntitiesDataContext.FiltronFilters.Where(
                    filt => filt.filter_shape_id.Equals(filterShape)
                        );
                if (dimA > 0) {
                    filters = filters.Where(filt => filt.filter_dim_a > dimA - dimAdiff && filt.filter_dim_a < dimA + dimAdiff);
                }
                if (dimB > 0)
                {
                    filters = filters.Where(filt => filt.filter_dim_b > dimB - dimBdiff && filt.filter_dim_b < dimB + dimBdiff);
                }
                if (dimC > 0)
                {
                    filters = filters.Where(filt => filt.filter_dim_c > dimC - dimCdiff && filt.filter_dim_c < dimC + dimCdiff);
                }
                if (dimD > 0)
                {
                    filters = filters.Where(filt => filt.filter_dim_d > dimD - dimDdiff && filt.filter_dim_d < dimD + dimDdiff);
                }
                if (dimE > 0)
                {
                    filters = filters.Where(filt => filt.filter_dim_e > dimE - dimEdiff && filt.filter_dim_e < dimE + dimEdiff);
                }
                if (dimF > 0)
                {
                    filters = filters.Where(filt => filt.filter_dim_f > dimF - dimFdiff && filt.filter_dim_f < dimF + dimFdiff);
                }
                if (dimG > 0)
                {
                    filters = filters.Where(filt => filt.filter_dim_g > dimG - dimGdiff && filt.filter_dim_g < dimG + dimGdiff);
                }
                if (dimH > 0)
                {
                    filters = filters.Where(filt => filt.filter_dim_h > dimH - dimHdiff && filt.filter_dim_h < dimH + dimHdiff);
                }
                
                if (!(filters.Any()))
                {
                    return null;
                }   //if
                filters = filters.Take(5);
                return filters;
            }   //try
            catch (Exception ex)
            {
                MyLogger.Log(ex);
            }   //catch
            return null;
        }
        /// <summary>
        /// Pobieranie obiektow na podstawie wymiarow.
        /// </summary>
        /// <param name="height">wysokosc</param>
        /// <param name="width">szerokosc</param>
        /// <param name="length">dlugosc</param>
        /// <param name="outsideDiaTop">zewnetrzna gorna srednica</param>
        /// <param name="outsideDiaBottom">zewnetrzna dolna srednica</param>
        /// <param name="insideDiaTop">wewnetrzna gorna srednica</param>
        /// <param name="insideDiaBottom">wewnetrzna dolna srednica</param>
        /// <returns>rekordy o zadanych wymiarach lub null, gdy nie ma</returns>
        public IQueryable<FiltronFilter> FindByDimensionsPaginated(
            decimal dimA, int dimAdiff,
            decimal dimB, int dimBdiff,
            decimal dimC, int dimCdiff,
            decimal dimD, int dimDdiff,
            decimal dimE, int dimEdiff,
            decimal dimF, int dimFdiff,
            decimal dimG, int dimGdiff,
            decimal dimH, int dimHdiff,
            int filterShape, int start, int offset)
        {
            try
            {
                IQueryable<FiltronFilter> filters = this._cmsEntitiesDataContext.FiltronFilters.Where(
                    filt => filt.filter_shape_id.Equals(filterShape)
                        );
                if (dimA > 0)
                {
                    filters = filters.Where(filt => filt.filter_dim_a > dimA - dimAdiff && filt.filter_dim_a < dimA + dimAdiff);
                }
                if (dimB > 0)
                {
                    filters = filters.Where(filt => filt.filter_dim_b > dimB - dimBdiff && filt.filter_dim_b < dimB + dimBdiff);
                }
                if (dimC > 0)
                {
                    filters = filters.Where(filt => filt.filter_dim_c > dimC - dimCdiff && filt.filter_dim_c < dimC + dimCdiff);
                }
                if (dimD > 0)
                {
                    filters = filters.Where(filt => filt.filter_dim_d > dimD - dimDdiff && filt.filter_dim_d < dimD + dimDdiff);
                }
                if (dimE > 0)
                {
                    filters = filters.Where(filt => filt.filter_dim_e > dimE - dimEdiff && filt.filter_dim_e < dimE + dimEdiff);
                }
                if (dimF > 0)
                {
                    filters = filters.Where(filt => filt.filter_dim_f > dimF - dimFdiff && filt.filter_dim_f < dimF + dimFdiff);
                }
                if (dimG > 0)
                {
                    filters = filters.Where(filt => filt.filter_dim_g > dimG - dimGdiff && filt.filter_dim_g < dimG + dimGdiff);
                }
                if (dimH > 0)
                {
                    filters = filters.Where(filt => filt.filter_dim_h > dimH - dimHdiff && filt.filter_dim_h < dimH + dimHdiff);
                }

                if (!(filters.Any()))
                {
                    return null;
                }   //if
                filters = filters.Skip(start).Take(offset);
                return filters;
            }   //try
            catch (Exception ex)
            {
                MyLogger.Log(ex);
            }   //catch
            return null;
        }
    }
}
